package com.ft.utils;

import com.ft.config.properties.WeiXinPayProperties;
import com.ft.domain.WeiXinPayToUniapp;
import com.github.wxpay.sdk.WXPayConstants;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.security.MessageDigest;
import java.util.*;

/**
 * @Author: ft
 * @Date: 2022/10/10/9:26
 * @Description:
 */
public class WxPayUtils {
   //秘钥
    private static final String key = "YQF25HK9QYBJH7WCW8OO95R67XW35BBO";

    /**
     * 将map转换为xml的字符串
     * @param data
     * @return
     * @throws Exception
     */
    public static String sendPost(Map<String,String> data) throws Exception{
        Set<String> strings = data.keySet();
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key: data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        }
        catch (Exception ex) {
        }
        return output;
    }

    /**
     * 将预支付订单xml转成返回uniapp的数据类型
     * @param xmlString 预支付返回结果
     * @return 返回给前端的对象
     */
    public static Map<String, String> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream is = getStringStream(xmlString);
        Document document = builder.parse(is);

        //获取到document里面的全部结点
        NodeList allNodes = document.getFirstChild().getChildNodes();
        Node node;
        Map<String, String> map = new HashMap<String, String>();
        int i = 0;
        while (i < allNodes.getLength()) {
            node = allNodes.item(i);
            if (node instanceof Element) {
                map.put(node.getNodeName(), node.getTextContent());
            }
            i++;
        }
        return map;
    }
    public static InputStream getStringStream(String sInputString) throws UnsupportedEncodingException {
        ByteArrayInputStream tInputStringStream = null;
        if (sInputString != null && !sInputString.trim().equals("")) {
            tInputStringStream = new ByteArrayInputStream(sInputString.getBytes("UTF-8"));
        }
        return tInputStringStream;
    }
    /**
     *   将xml转换成的map集合转换成WeiXinPayToUniapp对象返回前端
     */
    public static WeiXinPayToUniapp wxReturn(Map<String, String> xmlMap) throws Exception {
        //返回给前端的对象
        WeiXinPayToUniapp wxup = new WeiXinPayToUniapp();
        //签名验证的map
        Map<String, String> map = new HashMap<String,String>();
        //给返回结果封装数据
        wxup.setPackAge("prepay_id="+xmlMap.get("prepay_id"));
        wxup.setProvider("wxpay");
        wxup.setNonceStr(xmlMap.get("nonce_str"));
        String stime = String.valueOf(System.currentTimeMillis() / 1000);
        wxup.setTimeStamp(stime);
        wxup.setSignType("MD5");
        //给待签名的map赋值
        map.put("appId",xmlMap.get("appid"));
        map.put("nonceStr", wxup.getNonceStr());
        map.put("package",wxup.getPackAge());
        map.put("signType", wxup.getSignType());
        map.put("timeStamp", wxup.getTimeStamp());
        System.out.println("-----进入获取秘钥---"+key);
        wxup.setPaySign(Md5Sgin(map,key));
        System.out.println("待签名的map值是："+map);
        System.out.println("生成的返回签名是："+Md5Sgin(map,key));
        return wxup;
    }
    /**
     * 微信支付：生成MD5加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */

    public static String Md5Sgin(final Map<String, String> data, final String key) throws Exception {

        Set<String> keySet = data.keySet();

        String[] keyArray = keySet.toArray(new String[keySet.size()]);

        Arrays.sort(keyArray);

        StringBuilder sb = new StringBuilder();

        for (String k : keyArray) {

            if (k.equals(WXPayConstants.FIELD_SIGN)) {

                continue;

            }

            if (data.get(k).trim().length() > 0) // 参数值为空，则不参与签名

            {
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
            }

        }

        String result = sb.append("key=" + key).toString();
        System.out.println("MD5加密转换后的值是："+result);
        return MD5(result).toUpperCase();

    }

    /**
     * 生成 MD5
     *
     * @param
     * @param data 待处理数据
     * @return MD5结果
     */

    public static String MD5(String data) throws Exception {

        java.security.MessageDigest md = MessageDigest.getInstance("MD5");

        byte[] array = md.digest(data.getBytes("UTF-8"));

        StringBuilder sb = new StringBuilder();

        for (byte item : array) {

            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));

        }

        return sb.toString().toUpperCase();

    }
}
